﻿using movie.tool.library.hash;
using movie.tool.module.film.model;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;
using System.Threading.Tasks;

namespace movie.tool.module.http
{
    public class MovieClient
    {
        /// <summary>
        /// 修改剧本信息
        /// </summary>
        /// <param name="movie">剧本配置信息</param>
        /// <param name="movidId">剧本id</param>
        /// <returns></returns>
        public static async Task<bool> UpdateMovieInfo(MovieConfig movie,long movieId)
        {
            HttpContent content = JsonContent.Create(movie);
            return await HttpInvoker.PutAsync("movieserver/movies/" + movieId, content);
        }
        /// <summary>
        /// 保存封面
        /// </summary>
        /// <param name="filePath">封面文件的全路径</param>
        /// <param name="storePath">封面文件在剧本中的存储路径,相对剧本根目录</param>
        /// <param name="movieId">剧本id</param>
        /// <returns>请求成功返回true,否则false</returns>
        public static async Task<bool> UpdateMovieCover(string filePath,string storePath,long movieId)
        {
            var content = new MultipartFormDataContent();
            content.Add(new ByteArrayContent(File.ReadAllBytes(filePath)), "file", Path.GetFileName(filePath));
            content.Add(new StringContent(storePath), "path");
            return await HttpInvoker.PostAsync("movieserver/movies/" + movieId + "/cover", content);
        }
        /// <summary>
        /// 增加剧幕
        /// </summary>
        /// <param name="sceneConfig">新增加剧幕信息</param>
        /// <param name="movieId">剧本id</param>
        /// <returns>如果添加成功,返回新增加的剧幕id否则为null</returns>
        public static async Task<long?> SaveScene(SceneConfig sceneConfig,long movieId)
        {
            JsonContent content = JsonContent.Create<SceneConfig>(sceneConfig);
            return await HttpInvoker.PostAsync<long?>("movieserver/movieScenes/movie/" + movieId, content);
        }
        /// <summary>
        /// 修改剧幕信息
        /// </summary>
        /// <param name="sceneConfig">剧幕信息</param>
        /// <returns>成功返回true否则false</returns>
        public static async Task<bool> UpdateScene(SceneConfig sceneConfig)
        {
            HttpContent content = JsonContent.Create(sceneConfig);
            return await HttpInvoker.PutAsync("movieserver/movieScenes/" + sceneConfig.Id, content);
        }
        /// <summary>
        /// 判断文件是否跟远程剧幕的文件一致
        /// </summary>
        /// <param name="filePath">本地文件路径</param>
        /// <param name="movieSceneId">剧幕id</param>
        /// <returns>相同返回true,否则false</returns>
        public static async Task<bool> SceneFileEquals(string filePath, long movieSceneId)
        {
            string digest = await SceneFileDigest(movieSceneId);
            string localDigest = SHA1Hash.FileDigest(filePath);
            return localDigest.Equals(digest);
        }
        public static async Task<string> SceneFileDigest(long movieSceneId)
        {
            return await HttpInvoker.GetAsync<string>("movieserver/movieScenes/" + movieSceneId + "/digest");
        }
        /// <summary>
        /// 上传剧幕文件
        /// </summary>
        /// <param name="filePath">剧幕文件路径，文件全路径</param>
        /// <param name="movieSceneId">剧幕id</param>
        /// <returns>上传成功返回true,否则false</returns>
        public static async Task<bool> UploadSceneFile(string filePath,long movieSceneId)
        {
            using (var formContent = new MultipartFormDataContent())
            {
                StreamContent streamContent = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read));
                formContent.Add(streamContent, "file", Path.GetFileName(filePath));
                return await HttpInvoker.PostAsync("movieserver/movieScenes/" + movieSceneId + "/file", formContent);
            }  
        }
        public static async Task<bool> UploadSceneFileObs(string filePath, long movieSceneId, FileDigestParam digest)
        {
            if (movie_tool.App.APP_FOR_TEST)
            {
                //测试版本不能使用OBS上传
                return false;
            }
            JsonContent content = JsonContent.Create(digest);
            ObsSignedUrl url = await HttpInvoker.PutAsync<ObsSignedUrl>("movieserver/movieScenes/" + movieSceneId + "/digest", content);
            if (!url.Exist)
            {
                return await HttpInvoker.UploadObsFile(url, filePath);
            }
            return true;
        }
        /// <summary>
        /// 保存线索分组
        /// </summary>
        /// <param name="clueCardGroup">线索分组信息</param>
        /// <param name="movieId">剧本id</param>
        /// <returns>保存成功返回线索分组的id否则返回null</returns>
        public static async Task<long?> SaveClueCardGroup(ClueCardGroupConfig clueCardGroup,long movieId)
        {
            JsonContent content = JsonContent.Create<ClueCardGroupParam>(clueCardGroup);
            return await HttpInvoker.PostAsync<long?>("movieserver/clueCardGroups/movie/" + movieId, content);
        }

        public static async Task<bool> UpdateMovieAssist(string filePath, string storePath, long movieId)
        {
            var content = new MultipartFormDataContent();
            content.Add(new ByteArrayContent(File.ReadAllBytes(filePath)), "file", Path.GetFileName(filePath));
            content.Add(new StringContent(storePath), "path");
            return await HttpInvoker.PostAsync("movieserver/movies/" + movieId + "/assist", content);
        }

        /// <summary>
        /// 更新线索分组信息
        /// </summary>
        /// <param name="clueCardGroup">线索分组信息</param>
        /// <returns>保存成功返回true,否则false</returns>
        public static async Task<bool> UpdateClueCardGroup(ClueCardGroupConfig clueCardGroup)
        {
            JsonContent content = JsonContent.Create<ClueCardGroupParam>(clueCardGroup);
            return await HttpInvoker.PutAsync("movieserver/clueCardGroups/" + clueCardGroup.Id, content);
        }
        /// <summary>
        /// 新增线索
        /// </summary>
        /// <param name="clueCard">线索信息</param>
        /// <param name="clueCardGroupId">线索分组id</param>
        /// <returns>新增线索的id，如果新增失败,则返回null</returns>
        public static async Task<long?> SaveClueCard(ClueCardConfig clueCard,long clueCardGroupId)
        {
            JsonContent content = JsonContent.Create<ClueCardParam>(clueCard);
            return await HttpInvoker.PostAsync<long?>("movieserver/clueCards/group/" + clueCardGroupId, content);
        }
        /// <summary>
        /// 更新线索信息
        /// </summary>
        /// <param name="clueCard">线索信息</param>
        /// <returns>更新成功返回true,否则false</returns>
        public static async Task<bool> UpdateClueCard(ClueCardConfig clueCard)
        {
            JsonContent content = JsonContent.Create<ClueCardParam>(clueCard);
            return await HttpInvoker.PutAsync("movieserver/clueCards/" + clueCard.Id, content);
        }
        /// <summary>
        /// 本地文件是否与指定的线索卡高清文件相同
        /// </summary>
        /// <param name="filePath">文件全路径</param>
        /// <param name="clueCardId">线索id</param>
        /// <returns></returns>
        public static async Task<bool> ClueCardHdFileEquals(string filePath, long clueCardId)
        {
            string digest = await HttpInvoker.GetAsync<string>("movieserver/clueCards/" + clueCardId + "/hdDigest");
            string localDigest = SHA1Hash.FileDigest(filePath);
            return localDigest.Equals(digest);
        }
        /// <summary>
        /// 上传线索高清文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="clueCardId">线索id</param>
        /// <param name="relativePath">线索存储目录,相对剧本根目录</param>
        /// <returns>上传成功返回true,否则false</returns>
        public static async Task<bool> UploadClueCardHdFile(string filePath, long clueCardId,string relativePath)
        {
            if (await UploadClueCardHdFileObs(filePath, clueCardId, relativePath))
            {
                return true;
            }
            MultipartFormDataContent formContent = new MultipartFormDataContent();
            formContent.Add(new ByteArrayContent(File.ReadAllBytes(filePath)), "file", Path.GetFileName(filePath));
            formContent.Add(new StringContent(relativePath), "path");
            return await HttpInvoker.PostAsync("movieserver/clueCards/" + clueCardId + "/hdFile", formContent);
        }

        public static async Task<bool> UploadClueCardHdFileObs(string filePath, long clueCardId, string relativePath)
        {
            if (movie_tool.App.APP_FOR_TEST)
            {
                //测试版本不能使用OBS上传
                return false;
            }
            FileDigestParam param = new FileDigestParam();
            param.Sha1 = SHA1Hash.FileDigest(filePath);
            param.FileName = Path.GetFileName(filePath);
            param.Path = relativePath;
            JsonContent content = JsonContent.Create(param);
            ObsSignedUrl url = await HttpInvoker.PutAsync<ObsSignedUrl>("movieserver/clueCards/" + clueCardId + "/hdDigest", content);
            if (!url.Exist)
            {
                return await HttpInvoker.UploadObsFile(url, filePath);
            }
            return true;
        }
        /// <summary>
        /// 线索标清文件是否相同
        /// </summary>
        /// <param name="filePath">本地文件路径</param>
        /// <param name="clueCardId">线索id</param>
        /// <returns>相同返回true,否则false</returns>
        public static async Task<bool> ClueCardSdFileEquals(string filePath, long clueCardId)
        {
            string digest = await HttpInvoker.GetAsync<string>("movieserver/clueCards/" + clueCardId + "/sdDigest");
            string localDigest = SHA1Hash.FileDigest(filePath);
            return localDigest.Equals(digest);
        }
        /// <summary>
        /// 上传线索的标清文件
        /// </summary>
        /// <param name="filePath">本地文件路径</param>
        /// <param name="clueCardId">线索id</param>
        /// <param name="relativePath">线索文件存储路径,相对剧本根目录</param>
        /// <returns>上传成功返回true,否则false</returns>
        public static async Task<bool> UploadClueCardSdFile(string filePath, long clueCardId, string relativePath)
        {
            if(await UploadClueCardSdFileObs(filePath, clueCardId, relativePath))
            {
                return true;
            }
            MultipartFormDataContent formContent = new MultipartFormDataContent();
            formContent.Add(new ByteArrayContent(File.ReadAllBytes(filePath)), "file", Path.GetFileName(filePath));
            formContent.Add(new StringContent(relativePath), "path");
            return await HttpInvoker.PostAsync("movieserver/clueCards/" + clueCardId + "/sdFile", formContent);
        }

        public static async Task<bool> UploadClueCardSdFileObs(string filePath, long clueCardId, string relativePath)
        {
            if (movie_tool.App.APP_FOR_TEST)
            {
                //测试版本不能使用OBS上传
                return false;
            }
            FileDigestParam param = new FileDigestParam();
            param.Sha1 = SHA1Hash.FileDigest(filePath);
            param.FileName = Path.GetFileName(filePath);
            param.Path = relativePath;
            JsonContent content = JsonContent.Create(param);
            ObsSignedUrl url = await HttpInvoker.PutAsync<ObsSignedUrl>("movieserver/clueCards/" + clueCardId + "/sdDigest", content);
            if (!url.Exist)
            {
                return await HttpInvoker.UploadObsFile(url, filePath);
            }
            return true;
        }
        /// <summary>
        /// 保存玩家角色
        /// </summary>
        /// <param name="role">角色信息</param>
        /// <param name="movieId">剧本id</param>
        /// <returns>保存的角色id,如果保存失败,返回null</returns>
        public static async Task<long?> SavePlayerRole(PlayerRoleConfig role,long movieId)
        {
            JsonContent content = JsonContent.Create<PlayerRoleParam>(role);
            return await HttpInvoker.PostAsync<long?>("movieserver/playRoles/movie/" + movieId, content);
        }
        /// <summary>
        /// 更新角色信息
        /// </summary>
        /// <param name="role">角色信息</param>
        /// <returns>成功返回true,否则false</returns>
        public static async Task<bool> UpdatePlayerRole(PlayerRoleConfig role)
        {
            JsonContent content = JsonContent.Create<PlayerRoleParam>(role);
            return await HttpInvoker.PutAsync("movieserver/playRoles/" + role.Id, content);
        }
        /// <summary>
        /// 本地角色文件与远程是否一致
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public static async Task<bool> PlayerRoleFileEquals(string filePath, long roleId)
        {
            string digest = await HttpInvoker.GetAsync<string>("movieserver/playRoles/" + roleId + "/digest");
            string localDigest = SHA1Hash.FileDigest(filePath);
            return localDigest.Equals(digest);
        }
        /// <summary>
        /// 上传角色文件
        /// </summary>
        /// <param name="filePath">角色文件路径</param>
        /// <param name="roleId">角色id</param>
        /// <param name="relativePath">角色文件存储路径，相对剧本根目录</param>
        /// <returns></returns>
        public static async Task<bool> UploadPlayerRoleFile(string filePath, long roleId,string relativePath)
        {
            var formContent = new MultipartFormDataContent();
            formContent.Add(new ByteArrayContent(File.ReadAllBytes(filePath)), "file", Path.GetFileName(filePath));
            formContent.Add(new StringContent(relativePath), "path");
            return await HttpInvoker.PostAsync("movieserver/playRoles/" + roleId + "/file", formContent);
        }
        /// <summary>
        /// 保存章节
        /// </summary>
        /// <param name="chapter">章节信息</param>
        /// <param name="movieId">剧本id</param>
        /// <returns>新增加章节的id.如果保存失败,则返回null</returns>
        public static async Task<long?> SaveChapter(BookChapter chapter, long movieId)
        {
            JsonContent content = JsonContent.Create<BookChapter>(chapter);
            return await HttpInvoker.PostAsync<long?>("movieserver/chapters/movie/" + movieId, content);
        }
        /// <summary>
        /// 更新章节信息
        /// </summary>
        /// <param name="chapter">章节信息</param>
        /// <returns>成功返回true否则false</returns>
        public static async Task<bool> UpdateChapter(BookChapter chapter)
        {
            JsonContent content = JsonContent.Create<BookChapter>(chapter);
            return await HttpInvoker.PutAsync("movieserver/chapters/" + chapter.Id, content);
        }
        /// <summary>
        /// 本地剧本电子书是否与远程服务端相同
        /// </summary>
        /// <param name="filePath">本地电子书文件全路径</param>
        /// <param name="bookId">电子书id</param>
        /// <returns></returns>
        public static async Task<bool> BookFileEquals(string filePath, long bookId)
        {
            string digest = await HttpInvoker.GetAsync<string>("movieserver/playRoleBooks/" + bookId + "/digest");
            string localDigest = SHA1Hash.FileDigest(filePath);
            return localDigest.Equals(digest);
        }
        /// <summary>
        /// 保存电子书文件
        /// </summary>
        /// <param name="filePath">电子书文件本地路径</param>
        /// <param name="roleId">角色id</param>
        /// <param name="chapterId">章节id</param>
        /// <param name="relativePath">电子书文件存储路径，相对剧本根目录</param>
        /// <returns></returns>
        public static async Task<long?> UploadBookFile(string filePath,long roleId, long chapterId,string relativePath)
        {
            var formContent = new MultipartFormDataContent();
            formContent.Add(new ByteArrayContent(File.ReadAllBytes(filePath)), "file", Path.GetFileName(filePath));
            formContent.Add(new StringContent(relativePath), "path");
            return await HttpInvoker.PostAsync<long?>("movieserver/playRoleBooks/playRole/" + roleId + "/chapter/" + chapterId + "/file", formContent);
        }
        /// <summary>
        /// 发布剧本
        /// </summary>
        /// <param name="param">剧本发布参数</param>
        /// <param name="movieId">剧本id</param>
        /// <returns>发布进度查询key</returns>
        public static async Task<TaskKey> publish(MoviePublishParam param, long movieId)
        {
            JsonContent content = JsonContent.Create<MoviePublishParam>(param);
            return await HttpInvoker.PostAsync<TaskKey>("movieserver/movieInstances/movie/" + movieId, content);
        }
        /// <summary>
        /// 根据任务查询key查询任务的进度
        /// </summary>
        /// <param name="key">查询任务的key</param>
        /// <returns>任务当前进度</returns>
        public static async Task<TaskProgress> LoadProgress(TaskKey key)
        {
            int times = 3;
            TaskProgress tp = await HttpInvoker.GetAsync<TaskProgress>("movieserver/movieInstances/task/" + key.Key);
            while (tp == null && times > 0)
            {
                times--;
                await Task.Delay(1000);
                tp = await HttpInvoker.GetAsync<TaskProgress>("movieserver/movieInstances/task/" + key.Key);
            }
            return tp;
        }

        internal async static Task<bool> DeleteMovie(long id)
        {
            return await HttpInvoker.DeleteAsync("movieserver/movies/" + id);
        }
    }
}
